home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse3 / digets.sav < prev    next >
Encoding:
Text File  |  1990-09-13  |  44.9 KB  |  1,284 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DOCUMENT PROCESSOR                                 */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    DIGETS.C                                           */
  51. /*   AUTHOR:         Steven Lindeman, Fred Maples                       */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include <stdio.h>
  60. #include <search.h>
  61. #include <ctype.h>
  62. #include "didefs.h"
  63. #include "diglobal.h"
  64.  
  65. /*------------------------------------------------------*/
  66. /*                   G E T D E L I M                     */
  67. /*                   */
  68. /*        Called by:   GETTOKEN           */
  69. /*                   */
  70. /*        Returns:     ETAGO, STAGO, PIO, MDO,     */
  71. /*           DELIM, or EOF       */
  72. /*                   */
  73. /*             reads a delimeter from input           */
  74. /*------------------------------------------------------*/
  75. getdelim()
  76. {
  77.    register int inchar,retval;
  78.    switch(inchar=our_fgetc(indoc)) {
  79.    case '<':
  80.       switch(inchar=our_fgetc(indoc)) {
  81.       case '/':        /* found immediately after TAGO, */
  82.          if (isalpha(inchar=our_fgetc(indoc))) {
  83.             our_ungetc(inchar,indoc);
  84.             putstr_outbuf("\n[/");  /* so it's an endtag */
  85.             retval = ETAGO;
  86.          }
  87.          else {
  88.             our_ungetc(inchar,indoc);
  89.             unget_string("</");
  90.             retval = NODELIM;
  91.          }
  92.          break;
  93.       case '?':        /* found a processing instruction */
  94.          putstr_outbuf("\n[?");
  95.          retval = PIO;
  96.          break;
  97.       case '!':  /* found a markup declaration open */
  98.          if ((inchar=our_fgetc(indoc)) == '-')
  99.             if ((inchar=our_fgetc(indoc)) == '-') {
  100.                unget_string("--");
  101.                putstr_outbuf("<!");
  102.                retval = MDO;
  103.             }
  104.             else {
  105.                our_ungetc('-',indoc);
  106.                our_ungetc(inchar,indoc);
  107.                retval = NODELIM;
  108.             }
  109.          else
  110.             if (isalpha(inchar) || inchar=='[' || inchar==MARKUP_END) {
  111.                our_ungetc(inchar,indoc);
  112.                putstr_outbuf("<!");
  113.                retval = MDO;
  114.             }
  115.             else {
  116.                our_ungetc(inchar,indoc);
  117.                retval = NODELIM;
  118.             }
  119.          break;
  120.       default:
  121.          if (isalpha(inchar)) {
  122.             our_ungetc(inchar,indoc);
  123.             putstr_outbuf("\n[");
  124.             retval = STAGO;
  125.          }
  126.          else {
  127.             our_ungetc(inchar,indoc);
  128.             our_ungetc('<',indoc);
  129.             retval = NODELIM;
  130.          }
  131.          break;
  132.       }
  133.       break;
  134.    case EOF:
  135.       retval = EOF;  /* no more data */
  136.       break;
  137.    default:
  138.       our_ungetc(inchar,indoc);
  139.       retval = NODELIM;  /* no delimeter was found, probably data */
  140.       break;
  141.    }
  142.    return(retval);
  143. }
  144.  
  145. /*------------------------------------------------------*/
  146. /*          G E T C D A T A         */
  147. /*      This routine reads character data from 'indoc'.  */
  148. /* CDATA is terminated by an etago, delimiter   */
  149. /* in context.  That is a '</' followed by a name  */
  150. /* start character.           */
  151. /*                      */
  152. /*              returns -- NFDHT, FOUND            */
  153. /*------------------------------------------------------*/
  154. STATUS getcdata()
  155. {
  156.    int inchar;
  157.    unsigned num_cr;
  158.    char *outstr;
  159.    STATUS retval;
  160.    register BOOLEAN more_cdata,cr_found;
  161.    BOOLEAN firsttime;
  162.  
  163.    retval = NFDHT;
  164.    outstr = get_char_mem(2);
  165.    flush_buf();    
  166.    more_cdata = firsttime = TRUE;
  167.    num_cr = 0;
  168.  
  169.    while(more_cdata==TRUE && (inchar=our_fgetc(indoc))!=EOF) {
  170.       cr_found = save_crs(&num_cr,&inchar);
  171.       if (inchar == '<')
  172.          if ((inchar=our_fgetc(indoc)) == '/')
  173.             if (isalpha(inchar=our_fgetc(indoc))) {
  174.                more_cdata = FALSE;
  175.                our_ungetc(inchar,indoc);  /* unget in reverse order */
  176.                unget_string("</");
  177.             }
  178.             else {
  179.                retval = FOUND;
  180.                check_cr(&num_cr,cr_found,&firsttime,FALSE);
  181.                (*print_ctr)(ctrfp,"</");
  182.                (*applic)(DATA_STG,"</","");
  183.                our_ungetc(inchar,indoc);
  184.             }
  185.          else {
  186.             retval = FOUND;
  187.             check_cr(&num_cr,cr_found,&firsttime,FALSE);
  188.             (*put_ctr)('<',ctrfp);
  189.             (*applic)(DATA_STG,"<","");
  190.             our_ungetc(inchar,indoc);
  191.          }
  192.       else
  193.          if (inchar == OUR_EE) {
  194.             if (entstack[--entitylevel] != lookstack())
  195.                ourexit(2,"\nError: Entity End occurred in different character data.\n");
  196.          }
  197.          else {
  198.             retval = FOUND;
  199.             check_cr(&num_cr,cr_found,&firsttime,FALSE);
  200.             *outstr = inchar;
  201.             (*applic)(DATA_STG,outstr,"");
  202.             (*put_ctr)(inchar,ctrfp);
  203.          }
  204.    }
  205.    if (retval == FOUND)
  206.       (*put_ctr)('|',ctrfp);
  207.    free(outstr);
  208.    return(retval); 
  209. }
  210.  
  211. /*------------------------------------------------------*/
  212. /*                  G E T P C D A T A             */
  213. /* This routine reads parsable character data   */
  214. /* from 'indoc'.  PCDATA is terminated by an */
  215. /* etago, delimiter in context, given that all  */
  216. /* entities have been closed.  That is, a '</'  */
  217. /* followed by a name start character.  General */
  218. /* entities, as well as numeric and named char- */
  219. /* acter references are resolved.         */
  220. /*                      */
  221. /*              returns -- NFDHT, FOUND            */
  222. /*------------------------------------------------------*/
  223. STATUS getpcdata(genthead,penthead)
  224. ENTITYDESC *genthead,*penthead;
  225. {
  226.    int inchar,token,token2;
  227.    unsigned num_cr;
  228.    char *outstr;
  229.    BOOLEAN more_pcdata,more_subdata,cr_found,pcdata_ft;
  230.    STENTRY *tp;
  231.    TKNRETVAL tknretval;
  232.    STATUS retval;
  233.    TNODE *newcm;
  234.  
  235.    flush_buf();
  236.    outstr = get_char_mem(2);
  237.    num_cr = 0;
  238.    retval = NFDHT;
  239.    tknretval = TEXT;  /* so will read all the data first */
  240.    our_ungetc(inchar=our_fgetc(indoc),indoc);  /* initialize inchar */
  241.    token = -1;
  242.    tp = NULL; /* just to satisfy lint */
  243.    more_pcdata = pcdata_ft = TRUE;
  244.  
  245.    while(more_pcdata && inchar!=EOF) {
  246.       if (open_rcdata_ms)
  247.          retval = getrcdata(genthead,FALSE,&pcdata_ft,FALSE);
  248.       else
  249.          if (open_cdata_ms)
  250.             retval = get_cdata_ms(&pcdata_ft);
  251.          else
  252.             if (tknretval == TEXT) {
  253.                more_subdata = TRUE;
  254.                while(more_subdata && (inchar=our_fgetc(indoc))!=EOF) {
  255.                   cr_found = save_crs(&num_cr,&inchar);
  256.                   if (inchar == EOF)
  257.                      more_subdata = pcdata_ft = FALSE;
  258.                   else
  259.                      if (inchar == ']')
  260.                         if ((inchar=our_fgetc(indoc)) == ']')
  261.                            if ((inchar=our_fgetc(indoc)) == MARKUP_END) {
  262.                               if (--num_open_ms < 0)
  263.                                  ourexit(2,"\nError: Marked section end outside of declaration.\n");
  264.                            }
  265.                            else {
  266.                               retval = FOUND;
  267.                               check_cr(&num_cr,cr_found,&pcdata_ft,FALSE);
  268.                               our_ungetc(inchar,indoc);
  269.                               (*applic)(DATA_STG,"]]","");
  270.                               (*print_ctr)(ctrfp,"]]");
  271.                            }
  272.                         else {
  273.                            retval = FOUND;
  274.                            check_cr(&num_cr,cr_found,&pcdata_ft,FALSE);
  275.                            our_ungetc(inchar,indoc);
  276.                            (*put_ctr)(']',ctrfp);
  277.                            (*applic)(DATA_STG,"]","");
  278.                         }
  279.                      else
  280.                         if (inchar == '<')
  281.                            if ((inchar=our_fgetc(indoc)) == '/')
  282.                               if (isalpha(inchar=our_fgetc(indoc))) {
  283.                                  more_subdata = pcdata_ft = FALSE;
  284.                                  our_ungetc(inchar,indoc);
  285.                                  unget_string("</");
  286.                               }
  287.                               else {
  288.                                  retval = FOUND;
  289.                                  check_cr(&num_cr,cr_found,&pcdata_ft,FALSE);
  290.                                  (*print_ctr)(ctrfp,"</");
  291.                                  (*applic)(DATA_STG,"</","");
  292.                                  our_ungetc(inchar,indoc);
  293.                               }
  294.                            else  /* found markup */
  295.                            if (inchar=='?' || isalpha(inchar)) {
  296.                               more_subdata = pcdata_ft = FALSE;
  297.                               our_ungetc(inchar,indoc);
  298.                               our_ungetc('<',indoc);
  299.                            }
  300.                            else
  301.                               if (inchar == '!')
  302.                                  retval = check_for_mdo(&more_subdata,&num_cr,cr_found,&pcdata_ft);
  303.                               else {
  304.                                  retval = FOUND;
  305.                                  check_cr(&num_cr,cr_found,&pcdata_ft,FALSE);
  306.                                  (*put_ctr)('<',ctrfp);
  307.                                  (*applic)(DATA_STG,"<","");
  308.                                  our_ungetc(inchar,indoc);
  309.                               }
  310.                         else {
  311.                            retval = FOUND;
  312.                            check_cr(&num_cr,cr_found,&pcdata_ft,FALSE);
  313.                            try_entref(inchar,genthead,FALSE,&pcdata_ft);
  314.                         }
  315.                }
  316.                check_cr(&num_cr,cr_found,&pcdata_ft,TRUE);
  317.             }
  318.             else
  319.                if (find_except(currincl,token) && !find_except(currexcl,token)) {
  320.                   newcm = pushcreate(tp);
  321.                   if ((retval = traverse(newcm,tp,genthead,penthead,&pcdata_ft)) == NFSH) {
  322.                      if (tknretval == TEXT)
  323.                         sprintf(error_msg,"%s%s%s","\nError: Invalid data, last opened element '",tp->nametoken,"'.\n");
  324.                      else
  325.                         sprintf(error_msg,"%s%s%s","\nError: Invalid tag, last opened element '",tp->nametoken,"'.\n");
  326.                      FATAL_ERROR()
  327.                   }
  328.  
  329.                   /* check to make sure the element has content */
  330.                   if (EMPTY_CONTENT(newcm)) {   /* can't have endtag for EMPTY */
  331.                      token2 = token | HIGHBIT;
  332.                      putstr_outbuf("\n[/");
  333.                      putstr_outbuf(tp->nametoken);
  334.                      putstr_outbuf("]");
  335.                      place_in_queue(END_TAG_NAME,tp->nametoken,"");
  336.                   }
  337.                   else
  338.                      tknretval = gettoken(&tp,&token2,genthead,penthead,&pcdata_ft);  /* must be end tag */
  339.                   if (IS_STARTTAG(token2) || IS_ENDTAG_NOTEQ(token2,token))
  340.                      resolve_endtag(tp->cmptr,token2,tp,&retval,tknretval,genthead,penthead,token);
  341.                   popfree(newcm);  /* through with this content model */
  342.                }
  343.                else {
  344.                   more_pcdata = FALSE;
  345.                   ungettoken(token,tp);
  346.                }
  347.       if (more_pcdata)
  348.          tknretval = gettoken(&tp,&token,genthead,penthead,&pcdata_ft);
  349.    }
  350.    if (retval==FOUND && !cr_found)
  351.       (*put_ctr)('|',ctrfp);
  352.    free(outstr);
  353.    return(retval);
  354. }
  355.  
  356. /*------------------------------------------------------*/
  357. /*                  G E T R C D A T A        */
  358. /*      Reads 'indoc' for replaceable character data. */
  359. /* Entity references are resolved normally.  */
  360. /* RCDATA is terminated by an etago, delimiter  */
  361. /* in context.  That is a '</' followed by a name  */
  362. /* start character.           */
  363. /*                   */
  364. /*          returns -- NFDHT, FOUND          */
  365. /*------------------------------------------------------*/
  366. STATUS getrcdata(genthead,look_for_endtag,firsttime,end_of_data)
  367. ENTITYDESC *genthead;
  368. BOOLEAN look_for_endtag,*firsttime,end_of_data;
  369. {
  370.    int inchar,
  371.        prev_entitylevel;
  372.    unsigned num_cr;
  373.    BOOLEAN 
  374.        more_rcdata,
  375.        same_entity,
  376.        cr_found,
  377.        rcdata_ft;
  378.    STATUS retval;
  379.  
  380.    more_rcdata = same_entity = TRUE;
  381.    flush_buf();
  382.    retval = NFDHT;
  383.    num_cr = 0;
  384.    rcdata_ft = *firsttime;
  385.  
  386.    while(more_rcdata && (inchar=our_fgetc(indoc))!=EOF) {
  387.       cr_found = save_crs(&num_cr,&inchar);
  388.       if (inchar=='<' && look_for_endtag)
  389.          if ((inchar=our_fgetc(indoc)) == '/')
  390.             if (isalpha(inchar=our_fgetc(indoc)) && same_entity) {
  391.                more_rcdata = FALSE;
  392.                our_ungetc(inchar,indoc);  /* unget in reverse order */
  393.                unget_string("</"); 
  394.             }
  395.             else {
  396.                retval = FOUND;
  397.                check_cr(&num_cr,cr_found,&rcdata_ft,FALSE);
  398.                (*print_ctr)(ctrfp,"</");
  399.                (*applic)(DATA_STG,"</","");
  400.                our_ungetc(inchar,indoc);
  401.             }
  402.          else {
  403.             retval = FOUND;
  404.             check_cr(&num_cr,cr_found,&rcdata_ft,FALSE);
  405.             (*put_ctr)('<',ctrfp);
  406.             (*applic)(DATA_STG,"<","");
  407.             our_ungetc(inchar,indoc);
  408.          }
  409.       else
  410.          if (inchar==']' && !look_for_endtag)
  411.             if ((inchar=our_fgetc(indoc)) == ']')
  412.                if ((inchar=our_fgetc(indoc))==MARKUP_END && same_entity) {
  413.                   more_rcdata = open_rcdata_ms = FALSE;
  414.                   unget_string("]]>");
  415.                }
  416.                else {
  417.                   retval = FOUND;
  418.                   check_cr(&num_cr,cr_found,&rcdata_ft,FALSE);
  419.                   (*print_ctr)(ctrfp,"]]");
  420.                   (*applic)(DATA_STG,"]]","");
  421.                   our_ungetc(inchar,indoc);
  422.                }
  423.             else {
  424.                retval = FOUND;
  425.                check_cr(&num_cr,cr_found,&rcdata_ft,FALSE);
  426.                (*print_ctr)(ctrfp,"]");
  427.                (*applic)(DATA_STG,"]","");
  428.                our_ungetc(inchar,indoc);
  429.             }
  430.          else
  431.             if (inchar == OUR_EE) {
  432.                if (entstack[--entitylevel] != lookstack())
  433.                   ourexit(2,"\nError: Entity End occurred in different replaceable character data.\n");
  434.                check_cr(&num_cr,cr_found,&rcdata_ft,FALSE);
  435.                same_entity = TRUE;
  436.             }
  437.             else {
  438.                retval = FOUND;
  439.                check_cr(&num_cr,cr_found,&rcdata_ft,FALSE);
  440.                prev_entitylevel = entitylevel;
  441.                try_entref(inchar,genthead,FALSE,&rcdata_ft);
  442.                same_entity = (prev_entitylevel == entitylevel) ? TRUE : FALSE;
  443.             }
  444.    }
  445.    if (retval==FOUND && end_of_data)
  446.       (*put_ctr)('|',ctrfp);
  447.    return(retval); 
  448. }
  449.  
  450. /*------------------------------------------------------*/
  451. /*         G E T _ M A R K E D _ S E C T I O N          */
  452. /*     This routine processes a marked section.  If     */
  453. /*     the section is an INCLUDE section, processing  */
  454. /*     is returned to gettoken, else the entire section  */
  455. /*     is processed and then control is returned.  */
  456. /*------------------------------------------------------*/
  457. void get_marked_section(penthead)
  458. ENTITYDESC *penthead;
  459. {
  460.    register int inchar,statkey;
  461.    int begnum_open;
  462.    BOOLEAN moredata,close_read=FALSE;
  463.  
  464.    if ((inchar=our_fgetc(indoc)) != '[')
  465.       ourexit(2,"\nError: DSO not found in marked section.\n");
  466.  
  467.    statkey = get_status_keyword(penthead);
  468.    while(inputps(penthead) > 0)
  469.       gettilnosep();
  470.    if ((inchar=our_fgetc(indoc)) != '[')
  471.       ourexit(2,"\nError: DSO not found in marked section.\n");
  472.  
  473.    switch(statkey) {
  474.    case MS_INCLUDE:
  475.       break;
  476.    case MS_CDATA:
  477.       open_cdata_ms = TRUE;
  478.       break;
  479.    case MS_RCDATA:
  480.       open_rcdata_ms = TRUE;
  481.       break;
  482.    case MS_IGNORE:
  483.       begnum_open = num_open_ms-1;   /* already incremented */
  484.       moredata = TRUE;
  485.       while(moredata && (inchar=our_fgetc(indoc))!=EOF)
  486.          if (inchar=='<' && (inchar=our_fgetc(indoc))=='!' && (inchar=our_fgetc(indoc))=='[') {
  487.             if (++num_open_ms > TAGLVL)
  488.                ourexit(2,"\nError: Number open marked sections > TAGLVL.\n");
  489.          }
  490.          else
  491.             if (inchar==']' && (inchar=our_fgetc(indoc))==']' && (inchar=our_fgetc(indoc))==MARKUP_END) {
  492.                if (--num_open_ms == begnum_open)
  493.                   moredata = FALSE;
  494.             }
  495.             else
  496.                if (inchar == OUR_EE)
  497.                   ourexit(2,"\nError: Entity End found in IGNORE marked section.\n");
  498.       STRIP_CRs();
  499.       close_read = TRUE;
  500.       break;
  501.    default:
  502.       software_fault();
  503.       break;
  504.    }
  505.    if (!close_read && statkey!=MS_INCLUDE && statkey!=MS_CDATA && statkey!=MS_RCDATA) {
  506.       if ((inchar=our_fgetc(indoc))!=']' || (inchar=our_fgetc(indoc))!=']')
  507.          ourexit(2,"\nError: MDO not found in marked section.\n");
  508.       if ((inchar=our_fgetc(indoc)) != MARKUP_END)
  509.          ourexit(2,"\nError: MDC not found in marked section.\n");
  510.    }
  511.    return;
  512. }
  513.  
  514. /*------------------------------------------------------*/
  515. /*         G E T _ N A M E       */
  516. /* Reads from the input document for a valid */
  517. /* SGML name.  An error condition is raised if  */
  518. /* the length of the name is greater than NAMELEN. */
  519. /*------------------------------------------------------*/
  520. get_name(name,capitalize)
  521. char name[];
  522. int (*capitalize)();
  523. {
  524.    int inchar,indx;
  525.  
  526.    memset(name,'\0',NAMELEN+1);
  527.    indx=0;
  528.    if (isalpha(inchar=our_fgetc(indoc))) {
  529.       putchar_outbuf(name[indx++]=(*capitalize)(inchar));
  530.       fillup(name,&indx,capitalize);
  531.       if (indx > NAMELEN) {
  532.          sprintf(error_msg,"%s%s%s","\nError: Length of name beginning '",name,"' > NAMELEN\n");
  533.          FATAL_ERROR()
  534.       }
  535.    }
  536.    else {
  537.       name[indx++] = (*capitalize)(inchar);
  538.       fillup(name,&indx,capitalize);
  539.       sprintf(error_msg,"%s%s%s","\nError: Name '",name,"' must start with name start character\n");
  540.       FATAL_ERROR()
  541.    }
  542.    return(indx);
  543. }
  544.  
  545. /*------------------------------------------------------*/
  546. /*------------------------------------------------------*/
  547. /*------------------------------------------------------*/
  548. get_entname(name,capitalize)
  549. char name[];
  550. int (*capitalize)();
  551. {
  552.    int inchar,indx;
  553.  
  554.    memset(name,'\0',NAMELEN+1);
  555.    indx=0;
  556.    if (isalpha(inchar=our_fgetc(indoc))) {
  557.       name[indx++] = (*capitalize)(inchar);
  558.       fillup2(name,&indx,capitalize);
  559.       if (indx > NAMELEN) {
  560.          sprintf(error_msg,"%s%s%s","\nError: Length of name beginning '",name,"' > NAMELEN\n");
  561.          FATAL_ERROR()
  562.       }
  563.    }
  564.    else {
  565.       name[indx++] = (*capitalize)(inchar);
  566.       fillup2(name,&indx,capitalize);
  567.       sprintf(error_msg,"%s%s%s","\nError: Name '",name,"' must start with name start character\n");
  568.       FATAL_ERROR()
  569.    }
  570.    return(indx);
  571. }
  572.  
  573. /*------------------------------------------------------*/
  574. /*      G E T _ N U T O K E N       */
  575. /* Reads from the input document for a valid */
  576. /* SGML nutoken.  An error condition is raised  */
  577. /* if the length of the nutoken is greater than */
  578. /* NAMELEN.             */
  579. /*------------------------------------------------------*/
  580. get_nutoken(nutoken,capitalize)
  581. char nutoken[];
  582. int (*capitalize)();
  583. {
  584.    int inchar,indx;
  585.  
  586.    memset(nutoken,'\0',NAMELEN+1);
  587.    indx=0;
  588.    inchar=our_fgetc(indoc);
  589.    if (isdigit(inchar)) {      /* nutoken must start with numeral */
  590.       putchar_outbuf(nutoken[indx++]=(*capitalize)(inchar));
  591.       fillup(nutoken,&indx,capitalize);
  592.       if (indx > NAMELEN) {
  593.          sprintf(error_msg,"%s%s%s","\nError: Length of nutoken beginning '",nutoken,"' > NAMELEN\n");
  594.          FATAL_ERROR()
  595.       }
  596.    }
  597.    else {
  598.       nutoken[indx++] = (*capitalize)(inchar);
  599.       fillup(nutoken,&indx,capitalize);
  600.       sprintf(error_msg,"%s%s%s","\nError: Nutoken '",nutoken,"' must start with numeral.\n");
  601.       FATAL_ERROR()
  602.    }
  603.    return(indx);
  604. }
  605.  
  606. /*------------------------------------------------------*/
  607. /*      G E T _ N M T O K E N       */
  608. /* Reads from the input document for a valid */
  609. /* SGML nmtoken.  An error condition is raised  */
  610. /* if the length of the nmtoken is greater than */
  611. /* NAMELEN.             */
  612. /*------------------------------------------------------*/
  613. get_nmtoken(nmtoken,capitalize)
  614. char nmtoken[];
  615. int (*capitalize)();
  616. {
  617.    int indx=0;
  618.  
  619.    memset(nmtoken,'\0',NAMELEN+1);
  620.    fillup(nmtoken,&indx,capitalize);
  621.    if (indx > NAMELEN) {
  622.       sprintf(error_msg,"%s%s%s","\nError: Length of nmtoken beginning '",nmtoken,"' > NAMELEN\n");
  623.       FATAL_ERROR()
  624.    }
  625.    return(indx);
  626. }
  627.  
  628. /*------------------------------------------------------*/
  629. /*        G E T _ N U M B E R       */
  630. /* Reads from the input document for a valid */
  631. /* SGML number.  An error condition is raised   */
  632. /* if the length of the number is greater than  */
  633. /* NAMELEN.             */
  634. /*------------------------------------------------------*/
  635. get_number(number,capitalize)
  636. char number[];
  637. int (*capitalize)(); 
  638. {
  639.    int indx=0;
  640.    memset(number,'\0',NAMELEN+1);
  641.    while(isdigit(number[indx]=our_fgetc(indoc)) && indx<=NAMELEN)
  642.       putchar_outbuf(number[indx++]);
  643.    if (indx > NAMELEN) {
  644.       sprintf(error_msg,"%s%s%s","\nError: Length of number beginning '",number,"' > NAMELEN.\n");
  645.       FATAL_ERROR()
  646.    }
  647.    if (indx == 0) {
  648.       sprintf(error_msg,"%s%s%s","\nError: Invalid number, found '",number,"'.\n");
  649.       FATAL_ERROR()
  650.    }
  651.    our_ungetc(number[indx],indoc);
  652.    return(indx);
  653. }
  654.  
  655. /*------------------------------------------------------*/
  656. /*               G E T _ P I        */
  657. /* This routine reads a processing instruction  */
  658. /* from 'indoc'.   No parsing is done on the p.i.  */
  659. /* The p.i. is terminated by a TAGC.  The output   */
  660. /* buffer has already been flushed, therefore   */
  661. /* the p.i. is dumped directly into 'outdoc'.   */
  662. /*------------------------------------------------------*/
  663. void get_pi()
  664. {
  665.    register int inchar,pi_length;
  666.    char outpi[PILEN+1];
  667.  
  668.    pi_length = 0;
  669.    while((inchar=our_fgetc(indoc))!=MARKUP_END && inchar!=EOF && PILEN>pi_length) {
  670.       if (inchar == OUR_EE)
  671.          ourexit(2,"\nError: EE is invalid in processing instruction.\n");
  672.       else
  673.          (*put_ctr)(inchar,ctrfp);
  674.       outpi[pi_length++] = inchar;
  675.    }
  676.    (*put_ctr)(']',ctrfp);
  677.    STRIP_CRs();
  678.    if (pi_length > PILEN)
  679.       ourexit(2,"\nError: Length of processing instruction > PILEN.\n");
  680.    outpi[pi_length] = '\0';
  681.    (*applic)(PROC_INST,outpi,"");
  682.    return; 
  683. }
  684.  
  685. /*------------------------------------------------------*/
  686. /*           G E T _ S T A T U S _ K E Y W O R D        */
  687. /* This routine will parse the status keyword   */
  688. /* specification of a marked secttion declaration. */
  689. /* Zero or more status keywords are allowed in  */
  690. /* the specification.  If none is specified, the   */
  691. /* default of INCLUDE is returned.  If multiple */
  692. /* keywords are defined, the following priority */
  693. /* is used (highest shown first):         */
  694. /*       "IGNORE"       */
  695. /*       "CDATA"           */
  696. /*       "RCDATA"       */
  697. /*       "INCLUDE"         */
  698. /*------------------------------------------------------*/
  699. get_status_keyword(penthead)
  700. ENTITYDESC *penthead;
  701. {
  702.    int inchar,retval;
  703.    char keyname[NAMELEN+1];
  704.  
  705.    retval = MS_INCLUDE;  /* if none are specified, INCLUDE is assumed */
  706.    while(inputps(penthead) > 0);
  707.    gettilnosep();
  708.  
  709.    while((inchar=our_fgetc(indoc)) != '[') {
  710.       our_ungetc(inchar,indoc);
  711.       get_entname(keyname,our_toupper);
  712.       if (strcmp(keyname,"IGNORE") == 0)
  713.          retval = MAX(MS_IGNORE,retval);
  714.       else
  715.          if (strcmp(keyname,"CDATA") == 0)
  716.             retval = MAX(MS_CDATA,retval);
  717.          else
  718.             if (strcmp(keyname,"RCDATA") == 0)
  719.                retval = MAX(MS_RCDATA,retval);
  720.             else
  721.                if (strcmp(keyname,"INCLUDE") == 0)
  722.                   retval = MAX(MS_INCLUDE,retval);
  723.                else
  724.                   if (strcmp(keyname,"TEMP") != 0)
  725.                      ourexit(2,"\nError: Illegal status keyword in marked section\n");
  726.       while(inputps(penthead) > 0);
  727.       gettilnosep();
  728.    }
  729.    our_ungetc(inchar,indoc);
  730.    return(retval);
  731. }
  732.  
  733. /*--------------------------------------------------------------*/
  734. /*             G E T T O K E N         */
  735. /* This routine attempts at all costs to get a tag from  */
  736. /* the document.  If a tag has already been read and  */
  737. /* "ungettoken"d, then that tag is returned.  If not, */
  738. /* then parsing continues eating up all comments and  */
  739. /* processing instructions.  Marked sections are opened  */
  740. /* and processed as far as possible, meaning until data  */
  741. /* is found.                  */
  742. /*--------------------------------------------------------------*/
  743. TKNRETVAL gettoken(tp,token,genthead,penthead,get_ft)
  744. int *token;
  745. STPTR *tp;
  746. ENTITYDESC *genthead,*penthead;
  747. BOOLEAN *get_ft;
  748. {
  749.    char genid[NAMELEN+1];   /* generic identifier read from indoc */
  750.    int curr_delim,  /* current delimiter working with */
  751.       inchar,     /* current input character */
  752.       open_token;
  753.    unsigned
  754.        nleng_spec_list, /* normalized length of specification list */
  755.        num_id_idref;    /* number of ID and IDREF attribute values */
  756.    STENTRY *opened_tp;
  757.    TKNRETVAL retval;     /* either MARKUP_FOUND or TEXT */
  758.  
  759.    nleng_spec_list = num_id_idref = 0;
  760.    curr_delim = PIO;
  761.  
  762.    if (state == GETNEW) {
  763.       while(curr_delim==PIO || (curr_delim==MDO && !open_cdata_ms && !open_rcdata_ms)) { /* get input from input document */
  764.          flush_buf();
  765.          open_token = ((opened_tp=lookstack()) == NULL) ? rootid : opened_tp->tokenid;
  766.          if (num_open_ms > 0)
  767.             get_ms_closes();
  768.          if (symtable[open_token].content_type==ELEMENT_CONTENT && 
  769.                                            !open_cdata_ms && !open_rcdata_ms) {
  770.             while ((inchar=our_fgetc(indoc))=='&' || inchar==RE || inchar==RS ||
  771.                           inchar==SEPCHAR || inchar==SPACE || inchar==OUR_EE) {
  772.                try_entref(inchar,genthead,TRUE,&dontcare);
  773.                gettilnosep();
  774.             }
  775.             our_ungetc(inchar,indoc);
  776.          }
  777.          if (num_open_ms > 0)
  778.             get_ms_closes();
  779.  
  780.          switch(curr_delim=getdelim()) {
  781.          case NODELIM:  
  782.          case EOF:
  783.             retval = TEXT; /* if find EOF, just assume it was TEXT */
  784.             break;
  785.          case PIO:
  786.             retval = TEXT;  /* just an assumption */
  787.             flush_buf();  /* flush delimiter out */
  788.             *get_ft = TRUE;
  789.             get_pi();
  790.             break;
  791.          case MDO:
  792.             retval = TEXT;  /* just an assumption */
  793.             inchar = our_fgetc(indoc);
  794.             our_ungetc(inchar,indoc);
  795.             if (inchar == MARKUP_END) {  /* null comment */
  796.                CLEAR_BUF();  /* clear out MDO */
  797.                if ((inchar=our_fgetc(indoc)) != MARKUP_END)
  798.                   ourexit(2,"\nError: MDO not found for comment declaration\n");
  799.                STRIP_CRs();
  800.             }
  801.             else
  802.                if (inchar == '-') {   /* regular comment */
  803.                   CLEAR_BUF();  /* clear out MDO */
  804.                   while(inputps(penthead) > 0);
  805.                   if ((inchar=our_fgetc(indoc)) != MARKUP_END)
  806.                      ourexit(2,"\nError: MDO not found for comment declaration\n");
  807.                   STRIP_CRs();
  808.                }
  809.                else {
  810.                   CLEAR_BUF();   /* flush delimiter out */
  811.                   if (++num_open_ms > TAGLVL)
  812.                      ourexit(2,"\nError: Number of open marked sections > TAGLVL\n");
  813.                   get_marked_section(penthead);
  814.                }
  815.             break;
  816.          case ETAGO:
  817.             get_name(genid,our_toupper);
  818.             sprintf(lastread_tag,"</%s>",genid);
  819.             place_in_queue(END_TAG_NAME,genid,"");
  820.             retval = MARKUP_FOUND;
  821.             if ((*tp=(STPTR)bsearch(genid,symtable,numsym,sizeof(STENTRY),compare)) != NULL)
  822.                *token = (*tp)->tokenid;
  823.             else {
  824.                sprintf(error_msg,"%s%s%s","\nError: Unknown generic identifier '",genid,"' in endtag.\n");
  825.                FATAL_ERROR()
  826.             }
  827.             *token |= HIGHBIT;  /* turn high bit on for end tags */
  828.             gettilnosep();
  829.             if ((inchar=our_fgetc(indoc)) != MARKUP_END) {
  830.                sprintf(error_msg,"%s%s%s","\nError: TAGC not found for '",genid,"'.\n");
  831.                FATAL_ERROR()
  832.             }
  833.             putchar_outbuf(']');   /* TAGC to buffer */
  834.             STRIP_CRs();
  835.             *get_ft = TRUE;
  836.             break;
  837.          case STAGO:
  838.             retval = get_starttag(token,tp,genthead,get_ft,&nleng_spec_list,&num_id_idref);
  839.             break;
  840.          default:
  841.             software_fault();
  842.          }  /*switch*/
  843.       }  /*while*/
  844.    }
  845.    else {  /* get input from intermediate source, i.e. after ungettoken */
  846.       state = GETNEW;  /* next time get from document */
  847.       *token = holdtoken;
  848.       *tp = holdtp;
  849.       retval = MARKUP_FOUND;
  850.    }
  851.    if (nleng_spec_list > ATTSPLEN)
  852.       ourexit(2,"\nError: Normalized length of attribute spec list > ATTSPLEN\n");
  853.    if (num_id_idref > GRPCNT)
  854.       ourexit(2,"\nError: Total number of id reference names > GRPCNT.\n");
  855.    return(retval);
  856. }
  857.  
  858. /*--------------------------------------------------------------*/
  859. /*                    G E T _ S T A R T T A G                   */
  860. /* This routine handles the processing of a start tag.   */
  861. /* First the name of the tag is read and then a search   */
  862. /* is made to ensure that the name is a valid generic */
  863. /* identifier.  The attributes and their values are   */
  864. /* then read in and verified one at a time.     */
  865. /*--------------------------------------------------------------*/
  866. TKNRETVAL get_starttag(token,tp,genthead,get_ft,nleng_spec_list,num_id_idref)
  867. int *token;
  868. STPTR *tp;
  869. ENTITYDESC *genthead;
  870. BOOLEAN *get_ft;
  871. unsigned *nleng_spec_list,*num_id_idref;
  872. {
  873.    char genid[NAMELEN+1],   /* generic identifier read from indoc */
  874.         attrname[NAMELEN+1];  /* name of attribute value */
  875.    int inchar,     /* current input character */
  876.        leng,       /* length of attribute name */
  877.        temp_bufptr,
  878.        tagsize;     /* current length of tag */
  879.    ATTRDESC *thisadp;  /* points to description of attribute */
  880.    BOOLEAN notat_specified;
  881.    TKNRETVAL retval;     /* either MARKUP_FOUND or TEXT */
  882.  
  883.    notat_specified = FALSE;
  884.    tagsize = get_name(genid,our_toupper);
  885.    sprintf(lastread_tag,"<%s>",genid);
  886.    place_in_queue(TAG_NAME,genid,"");
  887.    retval = MARKUP_FOUND;
  888.    if ((*tp=(STPTR)bsearch(genid,symtable,numsym,sizeof(STENTRY),compare)) != NULL)
  889.       *token = (*tp)->tokenid;
  890.    else {
  891.       sprintf(error_msg,"%s%s%s","\nError: Unknown generic identifier '",genid,"'.\n");
  892.       FATAL_ERROR()
  893.    }
  894.    (*tp)->cmptr->contref_attr = FALSE;
  895.    unprocess((*tp)->adptr);
  896.    tagsize += gettilnosep();
  897.    temp_bufptr = bufptr;
  898.    while((inchar=our_fgetc(indoc)) != MARKUP_END) {
  899.       our_ungetc(inchar,indoc); 
  900.       putchar_outbuf(' ');
  901.       leng = get_name(attrname,our_toupper);
  902.       *nleng_spec_list += leng+NORMSEP;
  903.       tagsize += leng;
  904.       if ((thisadp=find_attr(attrname,(*tp)->adptr)) == NULL) {
  905.          sprintf(error_msg,"%s%s%s","\nError: Unknown attribute name'",attrname,"'.\n");
  906.          FATAL_ERROR()
  907.       }
  908.       else
  909.          if (thisadp->processed == TRUE) {
  910.             sprintf(error_msg,"%s%s%s","\nError: Duplicate attribute specifications '",thisadp->attrname,"'.\n");
  911.             FATAL_ERROR()
  912.          }
  913.          else
  914.             *nleng_spec_list += get_attrvalue(thisadp,genthead,&tagsize,&((*tp)->cmptr->contref_attr),&(notat_specified));
  915.       tagsize += gettilnosep(); 
  916.    }
  917.    bufptr = temp_bufptr;
  918.    if (req_not_proc((*tp)->adptr) == TRUE) {
  919.       sprintf(error_msg,"%s%s%s","\nError: REQUIRED or CURRENT attribute not specified '",
  920.       (*tp)->adptr->attrname,"'.\n");
  921.       FATAL_ERROR()
  922.    }
  923.    if (tagsize > TAGLEN)
  924.       ourexit(3,"\nLength of undelimited start tag > TAGLEN.\n");
  925.    *num_id_idref += resolve_attr((*tp)->adptr,FALSE);
  926.    place_in_queue(TAG_END,"","");
  927.    if ((*tp)->adptr == NULL)
  928.       putchar_outbuf(']');
  929.    else
  930.       putstr_outbuf("\n]");
  931.    STRIP_CRs();
  932.    *get_ft = FALSE;
  933.    return(retval);
  934. }
  935.  
  936. /*------------------------------------------------------*/
  937. /*             G E T _ A T T R V A L U E     */
  938. /* This routine processes the attribute value part */
  939. /* of an attribute specification.  The value is */
  940. /* checked for correctness in terms of syntax as   */
  941. /* well as semantics.            */
  942. /*------------------------------------------------------*/
  943. get_attrvalue(thisadp,genthead,taglen,contref,notat_specified)
  944. ATTRDESC *thisadp;
  945. ENTITYDESC *genthead;
  946. int *taglen;
  947. BOOLEAN *contref,*notat_specified;
  948. {
  949.    char name[NAMELEN+1],
  950.         buffer[ATTSPLEN+1],
  951.         idrefname[NAMELEN+1],
  952.         idname[NAMELEN+1];
  953.    unsigned
  954.       length,
  955.       nleng_attrval,
  956.       num_csdata;
  957.    register int inchar;
  958.    int delim,
  959.        val,
  960.        (*getone)();
  961.    BOOLEAN more_attr_vals;
  962.    GROUPDESC *groupptr;
  963.  
  964.    (*taglen) += gettilnosep()+1; 
  965.    length = 0; 
  966.    nleng_attrval = NORMSEP;
  967.    thisadp->processed = TRUE;   
  968.    if ((inchar=our_fgetc(indoc)) != '=')      /* name has already been read */
  969.       ourexit(2,"\nError: Invalid value indicator in attribute specification.\n");
  970.    putchar_outbuf('=');
  971.    (*taglen) += gettilnosep() + 1;
  972.  
  973.    if ((delim=our_fgetc(indoc))==LITA || delim==LIT)
  974.       putchar_outbuf(delim);
  975.    else
  976.       ourexit(2,"\nError: LIT or LITA not specified in attribute specification\n");
  977.  
  978.    BLANK(buffer,ATTSPLEN+1);
  979.  
  980.    switch(thisadp->dvcode) {
  981.    case NAME: 
  982.    case NAMES:
  983.    case NOTATION:
  984.       getone = get_name;
  985.       break;
  986.    case NUMBER: 
  987.    case NUMBERS:
  988.       getone = get_number;
  989.       break;
  990.    case NMTOKEN:
  991.    case NMTOKENS:
  992.    case GROUP:
  993.       getone = get_nmtoken;
  994.       break;
  995.    case NUTOKEN: 
  996.    case NUTOKENS:
  997.       getone = get_nutoken;
  998.       break;
  999.    }
  1000.  
  1001.    (*taglen) += process_attr(buffer,delim,genthead,thisadp->dvcode,&num_csdata);
  1002.    nleng_attrval += num_csdata*NORMSEP;
  1003.    (*taglen)++;  /* close delimiter */
  1004.  
  1005.    if (thisadp->dvcode != ENUM_CDATA)  {
  1006.       unget_string(buffer);
  1007.       gettilnosep();
  1008.    }
  1009.  
  1010.    if (thisadp->defcode == A_CONREF) {
  1011.       if (*notat_specified == TRUE)
  1012.          ourexit(2,"\nError: Content reference attribute not allowed with notation attribute.\n");
  1013.       *contref = TRUE;
  1014.    }
  1015.  
  1016.    more_attr_vals = TRUE;
  1017.  
  1018.    switch(thisadp->dvcode) {
  1019.    case ENUM_CDATA:
  1020.       putstr_outbuf(buffer);
  1021.       nleng_attrval += strlen(buffer);
  1022.       length = strlen(buffer);
  1023.       get_close(delim);
  1024.       check_fixed(thisadp->defcode,buffer,thisadp->u2.currdef,length);
  1025.       break;
  1026.    case GROUP:
  1027.    case NOTATION:
  1028.       length = (*getone)(name,our_toupper);  /* GROUP is actually a nmtoken */
  1029.       if (thisadp->dvcode == NOTATION) {
  1030.          if (*contref == TRUE) {
  1031.             sprintf(error_msg,"%s%s%s","\nError: Notation attribute '",name,"' specified after content reference.\n");
  1032.             FATAL_ERROR()
  1033.          }
  1034.          *notat_specified = TRUE;
  1035.       }
  1036.       nleng_attrval += length+NORMSEP;
  1037.  
  1038.       /* value must have been defined as part of the group */
  1039.       if ((groupptr=find_group(name,thisadp->groupp)) == NULL) {
  1040.          sprintf(error_msg,"%s'%s'.\n","\nError: Unknown attribute group member ",name);
  1041.          FATAL_ERROR()
  1042.       }
  1043.       else
  1044.          thisadp->u2.currgrp = groupptr;
  1045.       get_close(delim);
  1046.       check_fixed(thisadp->defcode,name,thisadp->u2.currgrp->groupname,NAMELEN);
  1047.       break;
  1048.    case NAME:  
  1049.    case NMTOKEN:  
  1050.    case NUTOKEN:  
  1051.    case NUMBER:
  1052.       length = (*getone)(buffer,our_toupper,FALSE);
  1053.       nleng_attrval += length+NORMSEP;
  1054.       get_close(delim);
  1055.       check_fixed(thisadp->defcode,buffer,thisadp->u2.currdef,strlen(thisadp->u2.currdef));
  1056.       break;
  1057.    case NUMBERS:  
  1058.    case NAMES:  
  1059.    case NMTOKENS:  
  1060.    case NUTOKENS:
  1061.       while(more_attr_vals) {   /* process each attribute value */
  1062.          /* in list, one at a time       */
  1063.          val = (*getone)(buffer+length,our_toupper);
  1064.          nleng_attrval += NORMSEP + val;
  1065.          length += val;
  1066.          if (gettilnosep() != 0)
  1067.             length++;
  1068.          more_attr_vals = ((inchar=our_fgetc(indoc)) != delim);
  1069.          if (inchar != delim) {
  1070.             putchar_outbuf(' ');
  1071.             our_ungetc(inchar,indoc);
  1072.          }
  1073.       }
  1074.       putchar_outbuf(inchar);
  1075.       check_fixed(thisadp->defcode,buffer,thisadp->u2.currdef,length);
  1076.       break;
  1077.    case ID:
  1078.       length = get_name(buffer,our_toupper);
  1079.       nleng_attrval += length+NORMSEP;
  1080.       strcpy(idname,buffer);
  1081.       get_close(delim);
  1082.       check_fixed(thisadp->defcode,buffer,thisadp->u2.currdef,strlen(thisadp->u2.currdef));
  1083.       break;
  1084.    case IDREF:  
  1085.       length = get_name(buffer,our_toupper);
  1086.       nleng_attrval += length+NORMSEP;
  1087.       strcpy(idrefname,buffer);
  1088.       get_close(delim);
  1089.       check_fixed(thisadp->defcode,buffer,thisadp->u2.currdef,strlen(thisadp->u2.currdef));
  1090.       break;
  1091.    case IDREFS:  
  1092.       while(more_attr_vals) {  /* process each attribute value */
  1093.          /* of the list one at a time    */
  1094.          val = get_name(buffer+length,our_toupper);
  1095.          strncpy(idrefname,buffer+length,val);
  1096.          length += val; 
  1097.          nleng_attrval += NORMSEP+val;
  1098.          if (gettilnosep() != 0)
  1099.             length++;
  1100.          more_attr_vals = ((inchar=our_fgetc(indoc)) != delim);
  1101.          if (inchar != delim) {
  1102.             putchar_outbuf(' ');
  1103.             our_ungetc(inchar,indoc);
  1104.          }
  1105.       }
  1106.       putchar_outbuf(inchar);
  1107.       check_fixed(thisadp->defcode,buffer,thisadp->u2.currdef,length);
  1108.       break;
  1109.    case ENTITY:
  1110.       length = get_name(name,nullfnc);
  1111.       nleng_attrval += length+NORMSEP;
  1112.       if (find_entity(genthead,name,FALSE) == NULL) {
  1113.          sprintf(error_msg,"%s'%s'.\n","\nError: Unknown attribute general entity name ",name);
  1114.          FATAL_ERROR()
  1115.       }
  1116.       check_fixed(thisadp->defcode,name,thisadp->u2.currdef,strlen(thisadp->u2.currdef));
  1117.       get_close(delim);
  1118.       break;
  1119.    default:
  1120.       software_fault();
  1121.       break;
  1122.    }
  1123.    if (nleng_attrval > LITLEN)
  1124.       ourexit(2,"\nError: Normalized length of attribute value > LITLEN\n");
  1125.    if (thisadp->dvcode!=NOTATION && thisadp->dvcode!=GROUP) {
  1126.       if (thisadp->u2.currdef != NULL)
  1127.          free(thisadp->u2.currdef);
  1128.       thisadp->u2.currdef = get_char_mem(length+1);
  1129.       buffer[length] = '\0';
  1130.       strcpy(thisadp->u2.currdef,buffer);
  1131.    }
  1132.    return(nleng_attrval);
  1133. }
  1134.  
  1135. /*------------------------------------------------------*/
  1136. /*               G E T _ C D A T A _ M S                */
  1137. /*------------------------------------------------------*/
  1138. STATUS get_cdata_ms(firsttime)
  1139. BOOLEAN *firsttime;
  1140. {
  1141.    BOOLEAN moredata,cr_found,cdata_ms_ft;
  1142.    STATUS retval;
  1143.    int inchar;
  1144.    unsigned num_cr;
  1145.    char *outstr;
  1146.  
  1147.    flush_buf();  
  1148.    retval = NFDHT; 
  1149.    cdata_ms_ft = *firsttime;
  1150.    outstr = get_char_mem(2);
  1151.    moredata = TRUE;
  1152.    while(moredata && (inchar=our_fgetc(indoc))!=EOF) {
  1153.       cr_found = save_crs(&num_cr,&inchar);
  1154.       if (inchar == ']')
  1155.          if ((inchar=our_fgetc(indoc)) == ']')
  1156.             if ((inchar=our_fgetc(indoc)) == MARKUP_END) {
  1157.                moredata = FALSE;
  1158.                our_ungetc(MARKUP_END,indoc);
  1159.                unget_string("]]");
  1160.             }
  1161.             else {
  1162.                retval = FOUND;
  1163.                check_cr(&num_cr,cr_found,&cdata_ms_ft,FALSE);
  1164.                (*print_ctr)(ctrfp,"]]%c",inchar);
  1165.                (*applic)(DATA_STG,"]]","");
  1166.                *outstr = inchar;
  1167.                (*applic)(DATA_STG,outstr,"");
  1168.             }
  1169.          else {
  1170.             retval = FOUND;
  1171.             check_cr(&num_cr,cr_found,&cdata_ms_ft,FALSE);
  1172.             (*print_ctr)(ctrfp,"]%c",inchar);
  1173.             (*applic)(DATA_STG,"]","");
  1174.             *outstr = inchar;
  1175.             (*applic)(DATA_STG,outstr,"");
  1176.          }
  1177.       else {
  1178.          retval = FOUND;
  1179.          check_cr(&num_cr,cr_found,&cdata_ms_ft,FALSE);
  1180.          (*put_ctr)(inchar,ctrfp);
  1181.          *outstr = inchar;
  1182.          (*applic)(DATA_STG,outstr,"");
  1183.       }
  1184.    }
  1185.    open_cdata_ms = FALSE;
  1186.    free(outstr);
  1187.    return(retval);
  1188. }
  1189.  
  1190. /*------------------------------------------------------*/
  1191. /*        G E T _ C L O S E         */
  1192. /* This routine reads from 'indoc' for the   */
  1193. /* delimeter passed to it as a parameter.  If   */
  1194. /* the delimeter is not found, an error is raised. */
  1195. /*------------------------------------------------------*/
  1196. void get_close(delim)
  1197. int delim;
  1198. {
  1199.    int inchar;
  1200.    if ((inchar=our_fgetc(indoc)) != delim)
  1201.       ourexit(2,"\nError: Lit or lita delimeter not found in attribute literal.\n");
  1202.    else
  1203.       putchar_outbuf(inchar);
  1204.    return;
  1205. }
  1206.  
  1207. /*------------------------------------------------------*/
  1208. /*               G E T T I L N O S E P                  */
  1209. /*      This routine reads from the file until a   */
  1210. /* non-seperator is found.                         */
  1211. /*------------------------------------------------------*/
  1212. gettilnosep()
  1213. {
  1214.    register int indx;
  1215.    int inchar;
  1216.  
  1217.    indx = 0;
  1218.    /* notice we aren't writing unneeded seperators to output file */
  1219.    inchar=our_fgetc(indoc);    /* get character from file */
  1220.    while(SEPERATOR(inchar)) {
  1221.       inchar=our_fgetc(indoc);
  1222.       indx++;
  1223.    }
  1224.    our_ungetc(inchar,indoc);
  1225.    return(indx);
  1226. }
  1227.  
  1228. /*------------------------------------------------------*/
  1229. /*       G E T _ C H A R _ M E M       */
  1230. /*      This routine allocates memory for character     */
  1231. /*      data and raises an error condition if there     */
  1232. /*      is insufficient memory for the allocation. */
  1233. /*------------------------------------------------------*/
  1234. char *get_char_mem(number)
  1235. int number;
  1236. {
  1237.    char *retptr,*calloc();
  1238.    if ((retptr=calloc(number,sizeof(char))) == NULL)
  1239.       ourexit(2,"\nInsufficient memory in parse3\n");
  1240.    return(retptr);
  1241. }
  1242.  
  1243. /*------------------------------------------------------*/
  1244. /*    G E T _ M S _ C L O S E S     */
  1245. /*   This routine reads from 'indoc' as many */
  1246. /*      marked section closes as possible.      */
  1247. /*------------------------------------------------------*/
  1248. void get_ms_closes()
  1249. {
  1250.    int inchar,open_token;
  1251.    STENTRY *opened_tp;
  1252.    BOOLEAN more_ms_closes=TRUE;
  1253.  
  1254.    while(more_ms_closes && (inchar=our_fgetc(indoc))!=EOF) {
  1255.       if (inchar == ']')
  1256.          if ((inchar=our_fgetc(indoc)) == ']')
  1257.             if ((inchar=our_fgetc(indoc)) == MARKUP_END) {
  1258.                if (--num_open_ms == 0)
  1259.                   more_ms_closes = FALSE;
  1260.                if ((inchar=our_fgetc(indoc)) != OUR_EE)
  1261.                   our_ungetc(inchar,indoc);
  1262.             }
  1263.             else {
  1264.                our_ungetc(inchar,indoc);  
  1265.                unget_string("]]");
  1266.                more_ms_closes = FALSE;
  1267.             }
  1268.          else {
  1269.             our_ungetc(inchar,indoc);
  1270.             our_ungetc(']',indoc);
  1271.             more_ms_closes = FALSE;
  1272.          }
  1273.       else {
  1274.          our_ungetc(inchar,indoc);
  1275.          more_ms_closes = FALSE;
  1276.       }
  1277.       open_token = ((opened_tp=lookstack()) == NULL) ? rootid : opened_tp->tokenid;
  1278.  
  1279.       if (symtable[open_token].content_type == ELEMENT_CONTENT)
  1280.          gettilnosep();   /* seperators are allowed between tags */
  1281.    }
  1282.    return;
  1283. }
  1284.